package cn.edu.sdjzu.knoverse.service.impl;

import cn.edu.sdjzu.knoverse.model.entity.kg.CourseNode;
import cn.edu.sdjzu.knoverse.model.entity.kg.UserNode;
import cn.edu.sdjzu.knoverse.model.entity.system.User;
import cn.edu.sdjzu.knoverse.model.vo.result.PageResult;
import cn.edu.sdjzu.knoverse.repository.CourseRepository;
import cn.edu.sdjzu.knoverse.repository.UserRepository;
import cn.edu.sdjzu.knoverse.service.CourseService;
import cn.edu.sdjzu.knoverse.service.UserService;
import cn.edu.sdjzu.knoverse.utils.exception.CustomException;
import cn.edu.sdjzu.knoverse.constant.EdgeConstant;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CourseServiceImpl implements CourseService {

    private final CourseRepository courseRepository;
    private final UserRepository userRepository;
    private final UserService userService;

    @Override
    @Transactional
    public CourseNode createCourse(CourseNode course) {
        return courseRepository.save(course);
    }

    @Override
    @Transactional
    public CourseNode updateCourse(CourseNode course) {
        CourseNode existingCourse = getCourse(course.getNodeId());
        if (existingCourse == null) {
            throw new CustomException("Course not found");
        }
        return courseRepository.save(course);
    }

    @Override
    @Transactional
    public void deleteCourse(Long id) {
        courseRepository.deleteById(id);
    }

    @Override
    public CourseNode getCourse(Long id) {
        return courseRepository.findById(id).orElse(null);
    }

    @Override
    public List<CourseNode> getAllCourses() {
        return courseRepository.findAll();
    }
    
    @Override
    public List<CourseNode> getCoursesByTeacherId(Long teacherId) {
        return courseRepository.findCoursesByTeacherId(teacherId);
    }
    
    @Override
    public PageResult<CourseNode> getCourseList(String name, String code, String description, Integer currentPage, Integer pageSize) {
        // 构建排序规则：按更新时间降序
        Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
        
        // 创建分页请求对象
        Pageable pageable = PageRequest.of(currentPage - 1, pageSize, sort);
        
        // 查询条件
        Page<CourseNode> coursePage;
        if (StringUtils.isAllBlank(name, code, description)) {
            // 无条件查询
            coursePage = courseRepository.findAll(pageable);
        } else {
            // 有条件查询
            coursePage = courseRepository.findByConditions(name, code, description, pageable);
        }
        
        // 构建返回结果
        return PageResult.<CourseNode>builder()
                .list(coursePage.getContent())
                .total(coursePage.getTotalElements())
                .pageNo(Long.valueOf(currentPage))
                .pageSize(Long.valueOf(pageSize))
                .build();
    }

    /**
     * 确保用户在图数据库中存在
     * 如果用户在关系数据库中存在但在图数据库中不存在，则创建用户节点
     */
    private UserNode ensureUserExists(Long userId) {
        // 先检查用户在图数据库中是否存在 userId 一样的节点，并非节点的id
        UserNode userNode = userRepository.findUserByUserId(userId);
        
        if (userNode != null) {
            return userNode;
        }
        // 用户在图数据库中不存在，检查关系数据库
        // 获取用户信息,无此用户会抛异常
        Object userInfoObj = userService.getUserInfo(userId);
        
        // 用户在关系数据库中存在，在图数据库中创建用户节点
        UserNode newUserNode = new UserNode();
        
        // 设置用户名称，如果有用户信息则使用用户信息中的名称
        if (userInfoObj instanceof User) {
            User userInfo = (User) userInfoObj;
            newUserNode.setName(userInfo.getUsername());
            newUserNode.setUserId(userInfo.getId());
        } else {
            newUserNode.setName("User-" + userId);
            newUserNode.setUserId(userId);
        }
        return userRepository.save(newUserNode);
    }

    @Override
    @Transactional
    public void updateCourseAccess(Long courseId, List<Long> userIds) {
        // 检查课程是否存在
        CourseNode course = getCourse(courseId);
        if (course == null) {
            throw new CustomException("Course not found");
        }

        // 确保将要添加的所有用户在图数据库中存在
        for (Long userId : userIds) {
            ensureUserExists(userId);
        }

        // 删除现有的所有TEACH关系
        courseRepository.deleteTeachRelationships(courseId);

        // 创建新的TEACH关系
        if (!userIds.isEmpty()) {
            courseRepository.createTeachRelationships(courseId, userIds);
        }
    }

    @Override
    public Set<UserNode> getCourseAccessList(Long courseId) {
        // 检查课程是否存在
        CourseNode course = getCourse(courseId);
        if (course == null) {
            throw new CustomException("Course not found");
        }
        Set<UserNode> list= userRepository.queryUserByCourseId(courseId);

        // 获取所有教师节点
        return list;
    }
    
    @Override
    @Transactional
    public void updatePreCourses(Long courseId, List<Long> preCourseIds) {
        // 检查当前课程是否存在
        CourseNode course = getCourse(courseId);
        if (course == null) {
            throw new CustomException("课程不存在");
        }
        
        // 验证前置课程列表中不包含当前课程自身
        if (preCourseIds.contains(courseId)) {
            throw new CustomException("前置课程不能包含当前课程自身");
        }
        
        // 验证所有前置课程是否存在
        for (Long preCourseId : preCourseIds) {
            CourseNode preCourse = getCourse(preCourseId);
            if (preCourse == null) {
                throw new CustomException("前置课程ID " + preCourseId + " 不存在");
            }
            
            // 检查添加此前置课程是否会导致循环依赖
            if (courseRepository.wouldCreateCyclicDependency(courseId, preCourseId)) {
                throw new CustomException("添加前置课程 '" + preCourse.getName() + "' 会导致循环依赖，无法添加");
            }
        }
        
        // 删除当前课程的所有前置课程关系
        courseRepository.deletePreCourseRelationships(courseId);
        
        // 获取PRE_COURSE关系的基本信息
        EdgeConstant preEdge = EdgeConstant.PRE_COURSE;
        String edgeName = preEdge.getName();
        String edgeDescription = preEdge.getDescription();
        
        // 创建新的前置课程关系
        for (Long preCourseId : preCourseIds) {
            courseRepository.createPreCourseRelationship(courseId, preCourseId, edgeName, edgeDescription);
        }
    }
    
    @Override
    public Set<CourseNode> getPreCourses(Long courseId) {
        // 检查课程是否存在
        CourseNode course = getCourse(courseId);
        if (course == null) {
            throw new CustomException("课程不存在");
        }
        
        // 获取所有前置课程
        return courseRepository.findPreCourses(courseId);
    }
} 